package cn.bluedot.tea.service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.alibaba.fastjson.JSONObject;

import cn.bluedot.framework.annotations.Dispatcher;
import cn.bluedot.framework.annotations.RequestView;
import cn.bluedot.framework.annotations.ResponseJson;
import cn.bluedot.framework.annotations.Service;
import cn.bluedot.framework.service.BaseService;
import cn.bluedot.framework.util.WebContext;
import cn.bluedot.framework.web.Result;
import cn.bluedot.tea.dao.BaseDao;
import cn.bluedot.tea.pojo.domain.User;
import cn.bluedot.tea.pojo.vo.BackupRecordVO;
import cn.bluedot.tea.pojo.vo.RunningLogMessage;
import cn.bluedot.tea.util.DataBackupAndReductionUtil;
import cn.bluedot.tea.util.Page;
import cn.bluedot.tea.util.PageBean;

@Service
public class SecurityService extends BaseService {

	private static Map<String, String> tableNameMap = new HashMap<String, String>();
	private final static String savePathPrefix = SecurityService.class.getResource("/").getPath().substring(1)+"backupSqls/";

	static {
		InputStream in = SecurityService.class.getClassLoader().getResourceAsStream("dataBackup.properties");
		Properties prop = new Properties();
		try {
			prop.load(in);
		} catch (IOException e) {
			System.err.println("dataBackup.properties 加载失败");
		}
		for (String name : prop.stringPropertyNames()) {
			tableNameMap.put(name, prop.getProperty(name));
		}

	}

	public SecurityService() {
	} // 无参构造函数，需要

	public SecurityService(String uri, Map<String, Object[]> params, Map<String, Object> data) {
		super(params, data); // 调用父类有参构造，必须
		execute(uri, params, data); // 执行业务，调用父类方法
	}

	/**
	 * 展示运行日志的详情
	 * @param params
	 * @param data
	 * @throws Exception
	 */
	@RequestView(uri = "/security/getLogInfo", view = "getLogInfo")
	@ResponseJson
	private void getLogInfo(Map<String, Object[]> params, Map<String, Object> data) throws Exception {
		Map<String, Object> param = getParameterMap(params);
		@SuppressWarnings("unchecked")
		List<LinkedHashMap<String, Object>> query = (List<LinkedHashMap<String, Object>>) BaseDao.excuteQuery(param,
				null);
		RunningLogMessage logMessage = null;
		for (LinkedHashMap<String, Object> runningLogMessage : query) {
			String runningLogMessageStr = (String) runningLogMessage.get("message");
			JSONObject runningLogMessageStrJson = JSONObject.parseObject(runningLogMessageStr);
			logMessage = (RunningLogMessage) JSONObject.toJavaObject(runningLogMessageStrJson, RunningLogMessage.class);
			int idRunningLog = (Integer) runningLogMessage.get("idRunningLog");
			logMessage.setIdRunningLog(idRunningLog);
			break;
		}
		if (logMessage == null) {
			data.put("RESULT", Result.FAILED);
			data.put("message", "找不到该条记录");
		} else {
			data.put("RESULT", Result.SUCCESS);
			data.put("logMessage", logMessage);
		}
	}

	/**
	 * 获取运行日志，包含分页功能
	 * @param params
	 * @param data
	 * @throws Exception
	 */
	@RequestView(uri = "/security/runningLogs/list", view = "getRunningLogs")
	@Dispatcher(success = "/security/run", failed = "/error")
	private void getRunningLogs(Map<String, Object[]> params, Map<String, Object> data) throws Exception {
		Map<String, Object> param = getParameterMap(params);
		// 处理当前页码
		String num = (String) param.get("pagenum");
		param.remove("pagenum");
		int pagenum = num == null ? 1 : Integer.parseInt(num);
		// 分页初始化
		Page.startPage(pagenum, 10);
		// 查询
		@SuppressWarnings("unchecked")
		List<LinkedHashMap<String, Object>> query = (List<LinkedHashMap<String, Object>>) BaseDao.excuteQuery(param,
				null);
		List<RunningLogMessage> queryResult = new ArrayList<RunningLogMessage>();
		for (LinkedHashMap<String, Object> runningLogMessage : query) {
			String runningLogMessageStr = (String) runningLogMessage.get("message");
			JSONObject runningLogMessageStrJson = JSONObject.parseObject(runningLogMessageStr);
			RunningLogMessage logMessage = (RunningLogMessage) JSONObject.toJavaObject(runningLogMessageStrJson,
					RunningLogMessage.class);
			int idRunningLog = (Integer) runningLogMessage.get("idRunningLog");
			logMessage.setIdRunningLog(idRunningLog);
			queryResult.add(logMessage);
		}
		// 封装PageBean
		PageBean<?> pageBean = new PageBean<>(queryResult, 10);
		// 写入data返回
		data.put("query", pageBean);
		data.put("RESULT", Result.SUCCESS);
	}

	/**
	 * 备份数据库
	 * 
	 * @throws Exception
	 */
	@RequestView(uri = "/security/backup", view = "insertBackupRecord")
	@ResponseJson
	private void backup(Map<String, Object[]> params, Map<String, Object> data) throws Exception {
		data.put("RESULT", Result.FAILED);
		String backupTableName = (String) params.get("backupTableName")[0];
		User user = (User) WebContext.getSession().getAttribute("user");
		Integer userId = user.getUserId();
		List<String> tableName = backupTableName2List(backupTableName);
		String savePath = savePathPrefix + userId + "-" + System.currentTimeMillis();
		DataBackupAndReductionUtil.dataBackup(tableName, savePath);
		BackupRecordVO backupRecordVO = new BackupRecordVO(backupTableName, userId, savePath,
				getTotalSizeOfFilesInDir(new File(savePath)));
		BaseDao.excute(getBackupRecordParam(backupRecordVO));
		data.put("RESULT", Result.SUCCESS);
	}
	
	@RequestView(uri = "/security/backup/list", view = "listBackRecord")
	@Dispatcher(success = "/security/re_backup", failed = "/error")
	private void listBackRecord(Map<String, Object[]> params, Map<String, Object> data) throws Exception {
		Map<String, Object> param = getParameterMap(params);
		//处理当前页码
		String num = (String) param.get("pagenum");
		param.remove("pagenum");
		int pagenum = num == null ? 1 : Integer.parseInt(num);
		//分页初始化
		Page.startPage(pagenum, 10);
		//查询
		List<?> query = (List<?>) BaseDao.excuteQuery(param, null);
		//封装PageBean
		PageBean<?> pageBean = new PageBean<>(query, 10);
		//写入data返回
		data.put("query", pageBean);
		data.put("RESULT", Result.SUCCESS);
	}

	private static Map<String, Object> getBackupRecordParam(BackupRecordVO backupRecordVO) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("view", "insertBackupRecord");
		param.put("backupType", backupRecordVO.getbackupType());
		param.put("backupTime", backupRecordVO.getbackupTime());
		param.put("backupUserid", backupRecordVO.getBackupUserid());
		param.put("backupDataPath", backupRecordVO.getBackupDataPath());
		param.put("backupDataSize", backupRecordVO.getBackupDataSize());
		return param;
	}

	/**
	 * 计算某个文件夹内所有文件的总大小
	 * 
	 * @param file
	 * @return
	 */
	private static long getTotalSizeOfFilesInDir(final File file) {
		if (file.isFile())
			return file.length();
		final File[] children = file.listFiles();
		long total = 0;
		if (children != null)
			for (final File child : children)
				total += getTotalSizeOfFilesInDir(child);
		return total;
	}

	/**
	 * 将前端传入的需要被备份的内容转化为数据库表名字的集合
	 * 
	 * @param backupTableName
	 * @return
	 */
	private List<String> backupTableName2List(String backupTableName) {
		List<String> tableNames = new ArrayList<String>();
		String[] names = backupTableName.split(",");
		for (int i = 0; i < names.length; i++) {
			if (tableNameMap.containsKey(names[i])) {
				tableNames.add(tableNameMap.get(names[i]));
			}
		}
		List<String> tablesName = new ArrayList<String>();
		for (String name : tableNames) {
			String[] names1 = name.split(" ");
			for (int i = 0; i < names1.length; i++) {
				if (!"".equals(names1[i].trim())) {
					tablesName.add(names1[i]);
				}
			}
		}
		return tablesName;
	}

	@RequestView(uri = "/security/reduction", view="getBackupDataPath")
	@ResponseJson
	private void reduction(Map<String, Object[]> params, Map<String, Object> data) throws Exception {
		data.put("RESULT", Result.FAILED);
		Map<String, Object> param = getParameterMap(params);
		List<?> query =  (List<?>) BaseDao.excuteQuery(param, null);
		@SuppressWarnings("unchecked")
		Map<String, String> queryMap = (Map<String, String>) query.get(0);
		String backupDataPath = (String) queryMap.get("backupDataPath");
		DataBackupAndReductionUtil.dataReduction(backupDataPath);
		data.put("RESULT", Result.SUCCESS);
	}
	
}
